﻿using System.Collections.Generic;
using System.Linq;
using Xenta.Api;
using Xenta.Entities;
using Xenta.Enums;
using Xenta.Security;
using Xenta.Utils;

namespace Xenta.Operations
{
    #region __General__

    /// <summary>
    /// Creates a seller address.
    /// </summary>
    public class CreateSellerAddress : CreateAddress<SellerAddressEntity>,
        ISecuredOperation, IApiOperation
    {
        #region Properties

        /// <summary>
        /// Gets the collection of security policies.
        /// </summary>
        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("SALES");
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .IsVerified()
                    .Rule((ctx, uow) =>
                    {
                        var seller = ctx.Seller(uow);
                        if(seller == null || !seller.Flags.HasFlag(SellerFlags.Active))
                            return false;
                        return seller.EntityID == HolderID;
                    });
            }
        }

        /// <summary>
        /// Gets or sets the flags.
        /// </summary>
        public SellerAddressFlags Flags
        {
            get;
            set;
        }

        #endregion

        #region Utilities

        protected override void Construct(IUnitOfWork uow, SellerAddressEntity entity)
        {
            base.Construct(uow, entity);

            entity.Flags = Flags;
        }

        #endregion
    }

    /// <summary>
    /// Updates the seller address.
    /// </summary>
    public class UpdateSellerAddress : UpdateAddress<SellerAddressEntity>,
        ISecuredOperation, IApiOperation
    {
        #region Properties

        /// <summary>
        /// Gets the collection of security policies.
        /// </summary>
        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("SALES");
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .IsVerified()
                    .Rule((ctx, uow) =>
                    {
                        var seller = ctx.Seller(uow);
                        if(seller == null || !seller.Flags.HasFlag(SellerFlags.Active))
                            return false;
                        var address = uow.Execute(new GetSellerAddress
                        {
                            EntityID = EntityID
                        }).Result;
                        if(address == null)
                            return false;
                        return address.HolderID == seller.EntityID;
                    });
            }
        }

        /// <summary>
        /// Gets or sets the flags.
        /// </summary>
        public SellerAddressFlags Flags
        {
            get;
            set;
        }

        #endregion

        #region Utilities

        protected override void Revise(IUnitOfWork uow, SellerAddressEntity entity)
        {
            base.Revise(uow, entity);

            entity.Flags = Flags;
        }

        #endregion
    }

    /// <summary>
    /// Deletes the seller address.
    /// </summary>
    public class DeleteSellerAddress : DeleteAddress<SellerAddressEntity>,
        ISecuredOperation, IApiOperation
    {
        #region Properties

        /// <summary>
        /// Gets the collection of security policies.
        /// </summary>
        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("SALES");
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .IsVerified()
                    .Rule((ctx, uow) =>
                    {
                        var seller = ctx.Seller(uow);
                        if(seller == null || !seller.Flags.HasFlag(SellerFlags.Active))
                            return false;
                        var address = uow.Execute(new GetSellerAddress
                        {
                            EntityID = EntityID
                        }).Result;
                        if(address == null)
                            return false;
                        return address.HolderID == seller.EntityID;
                    });
            }
        }

        #endregion
    }

    /// <summary>
    /// Gets the seller address by identifier.
    /// </summary>
    public class GetSellerAddress : GetAddress<SellerAddressEntity>,
        IApiOperation
    {
    }

    #endregion

    #region __Search__

    /// <summary>
    /// Search over seller address collection.
    /// </summary>
    public class SearchSellerAddresses : SearchAddresses<SellerAddressEntity>,
        IApiOperation
    {
        #region Ctors

        /// <summary>
        /// Initializes a new class instance.
        /// </summary>
        public SearchSellerAddresses()
        {
            SortBy = new []
            {
                SellerAddressSortBy.ID
            };
            SortDir = SortDirection.Ascending;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the flag mask.
        /// </summary>
        public SellerAddressFlags FlagMask
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the sort by.
        /// </summary>
        public SellerAddressSortBy[] SortBy
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the sort direction.
        /// </summary>
        public SortDirection SortDir
        {
            get;
            set;
        }

        #endregion

        #region Utilities

        protected override IQueryable<SellerAddressEntity> Build(IUnitOfWork uow, IQueryable<SellerAddressEntity> query)
        {
            query = base.Build(uow, query);
            query = query.FilterByFlags(x => x.FlagsValue, (int)FlagMask);
            if(SortBy != null)
            {
                for(int i = 0; i < SortBy.Length; i++)
                {
                    switch(SortBy[i])
                    {
                        case SellerAddressSortBy.CreatedOn:
                            query = query.OrderBy(x => x.CreatedOn, SortDir, i != 0);
                            break;
                        case SellerAddressSortBy.ContactName:
                            query = query.OrderBy(x => x.ContactName, SortDir, i != 0);
                            break;
                        default:
                            query = query.OrderBy(x => x.EntityID, SortDir, i != 0);
                            break;
                    }
                }
            }
            return query;
        }

        #endregion
    }

    #endregion
}
